package service

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/sirupsen/logrus"
	"io"
	"lib/jwt"
	"lib/structs/sys"
	"lib/structs/tables"
	"lib/utils"
	"net/http"
	"os"
	"path/filepath"
	"sys/dao"
	"sys/global"
	"time"
)

var UserServ = new(userService)

type userService struct {
}

func (ser userService) CallVapForAddWinUser(username string) (err error) {
	var (
		bs   []byte
		req  *http.Request
		resp *http.Response
	)
	in := struct {
		Accounts []string `json:"accounts"`
	}{}
	in.Accounts = []string{username}
	bs, err = json.Marshal(in)
	if err != nil {
		return
	}
	for _, uri := range global.Conf.RemoteApi.Vap {
		req, err = http.NewRequest("POST", fmt.Sprintf("%s%s", uri, "/api/vap/remote/createWinRdpAccount"), bytes.NewBuffer(bs))
		if err != nil {
			return
		}
		req.Header.Set("Content-Type", "application/json")
		client := &http.Client{}
		resp, err = client.Do(req)
		if err != nil {
			return
		}
		defer resp.Body.Close()
		if resp.StatusCode != http.StatusOK {
			body, _ := io.ReadAll(resp.Body)
			logrus.Errorf("callVapForAddWinUser http status code %d，err msg :%s", resp.StatusCode, string(body))
		}
	}
	return nil
}

// UserLogin 用户登录，返回token
func (ser userService) UserLogin(loginAccount sys.LoginAccount) (result sys.LoginSuccess, base jwt.BaseClaims, err error) {
	var (
		user        *tables.User
		rs          []string
		accessToken string
	)
	user, err = dao.UserDB.FindUserByAccount(loginAccount.Username)
	if err != nil {
		return
	}
	if user.Password != loginAccount.Password {
		return result, base, fmt.Errorf("密码错误: %v ", loginAccount)
	}
	j := jwt.NewJWT()
	rs = ser.getRoles(user.UserId)
	base = jwt.BaseClaims{
		UserID:    user.UserId,
		Username:  user.Username,
		Nickname:  user.Extend.Nickname,
		AccountLv: user.AccountLv,
		OrgId:     user.OrgId,
		Role:      rs,
	}
	accessToken, err = j.CreateToken(base, jwt.JWTAccessTime)
	result = sys.LoginSuccess{
		Username: user.Extend.Nickname,
		Roles:    rs,
		Token:    accessToken,
		Expires:  time.Now().Unix() + jwt.JWTAccessTime,
	}
	return
}

func (ser userService) RefreshToken(uid int64) (accessToken string, expires int64, err error) {
	var (
		user *tables.User
		base jwt.BaseClaims
		rs   []string
	)
	user, err = dao.UserDB.FindById(uid)
	if err != nil {
		return
	}
	rs = ser.getRoles(user.UserId)
	base = jwt.BaseClaims{
		UserID:    user.UserId,
		Username:  user.Username,
		Nickname:  user.Extend.Nickname,
		AccountLv: user.AccountLv,
		OrgId:     user.OrgId,
		Role:      rs,
	}
	j := jwt.NewJWT()
	accessToken, err = j.CreateToken(base, jwt.JWTAccessTime)
	expires = time.Now().Unix() + jwt.JWTAccessTime
	return
}

// getRoles 获取角色列表
func (ser userService) getRoles(uid int64) (rs []string) {
	var (
		li  []tables.Role
		err error
	)
	if li, err = dao.UserDB.FindUserRoleList(uid); err != nil {
		return []string{}
	}
	rs = make([]string, len(li))
	for i := range li {
		rs[i] = li[i].RoleCode
	}
	return rs
}

func (ser userService) GetPageMenu(uid int64) (pages []sys.PageMenuNode, err error) {
	var (
		p         string
		bs        []byte
		userRoles []string
	)
	if p, err = os.Executable(); err != nil {
		err = fmt.Errorf("GetPageMenu executable err :%v", err)
		return
	}
	bs, err = os.ReadFile(filepath.Join(filepath.Dir(p), "web_page.json"))
	if err != nil {
		err = fmt.Errorf("GetPageMenu ReadFile err :%v", err)
		return
	}
	routers := make([]sys.PageMenuNode, 0)
	err = json.Unmarshal(bs, &routers)
	if err != nil {
		return
	}
	userRoles = ser.getRoles(uid)
	pages = make([]sys.PageMenuNode, 0)
	for _, lv1 := range routers {
		if len(utils.IntersectForString(lv1.Meta.Roles, userRoles)) > 0 {
			plv1 := sys.PageMenuNode{
				Id:       lv1.Id,
				Path:     lv1.Path,
				Name:     lv1.Name,
				Redirect: lv1.Redirect,
				Meta:     lv1.Meta,
				Children: make([]sys.PageMenuNode, 0),
			}
			for _, lv2 := range lv1.Children {
				if len(utils.IntersectForString(lv2.Meta.Roles, userRoles)) > 0 {
					plv2 := sys.PageMenuNode{
						Id:       lv2.Id,
						Path:     lv2.Path,
						Name:     lv2.Name,
						Redirect: lv2.Redirect,
						Meta:     lv2.Meta,
						Children: make([]sys.PageMenuNode, 0),
					}
					plv1.Children = append(plv1.Children, plv2)
				}
			}
			pages = append(pages, plv1)
		}
	}
	return
}

//func (ser userService) GetRouterTreeForFile() (nodes []sys.RouterNode, err error) {
//	var (
//		p  string
//		bs []byte
//	)
//	if p, err = os.Executable(); err != nil {
//		return
//	}
//	bs, err = os.ReadFile(filepath.Join(filepath.Dir(p), "web_page.json"))
//	if err != nil {
//		return
//	}
//	routers := make([]sys.RouterNode, 0)
//	err = json.Unmarshal(bs, &routers)
//	if err != nil {
//		return
//	}
//	return
//}

// VerifyCode 检查验证码是否合法
func (ser userService) VerifyCode(ver sys.VeryCode) bool {
	return true
}

// CheckUpdateUserAuthority 检查是否有权限对改用户执行更新操作
func (ser userService) CheckUpdateUserAuthority(tar *tables.User, self *jwt.CustomClaims) (b bool) {
	if self.AccountLv == tables.AccountLvForRoot {
		return true
	}
	if tar.CreatorId == self.UserID {
		return true
	}
	return false
}

func (ser userService) GetUserList(uid int64, accountLv int) (li []tables.User, err error) {
	if accountLv == tables.AccountLvForRoot {
		li, err = dao.UserDB.FindList()
	} else {
		var orgIds []int64
		orgIds, err = dao.UserDB.FindOrgIds(uid)
		if err != nil {
			li = make([]tables.User, 0)
		} else {
			li, err = dao.UserDB.FindListByOrgIds(orgIds)
		}
	}
	return
}
